use core::fmt::{self, Write};

use crate::{
    boot::phys_to_io,
    drivers::console::{amba_pl011::Pl011, ConsoleImpl},
    sync::spinlock::Spinlock,
};

static PL011: Spinlock<Pl011> =
    Spinlock::new(Pl011 { regs: phys_to_io(0x9000000), clock: 100, baudrate: 115200 });

impl Write for Pl011 {
    fn write_str(&mut self, s: &str) -> fmt::Result {
        self.write(s.as_bytes());
        Ok(())
    }
}

/// 向控制台打印格式化字符
pub fn console_output(args: fmt::Arguments<'_>) {
    let mut lock = PL011.lock();
    lock.write_fmt(args).unwrap();
}

#[macro_export]
macro_rules! print {
    ($($arg:tt)*) => {{
        $crate::print::console_output(core::format_args!($($arg)*));
    }};
}

#[macro_export]
macro_rules! println {
    () => {
        $crate::print!("\n")
    };
    ($($arg:tt)*) => {{
        $crate::print::console_output(core::format_args_nl!($($arg)*));
    }};
}

/// 初始化控制台
pub fn console_init() {
    let mut lock = PL011.lock();
    lock.init();
}
